package com.ntschy.taizhou.threaddemo;

// 从项目中提取的id生成器

public class IdManager {

    private long lastTimestamp = -1L;
    private long sequence = 0L;

    private final long sequenceBits = 8L;
    private final long sequenceMask = -1L ^ (-1L << sequenceBits);

    private final long startEpoch = 1483200000000L;

    private final long workerIdBits = 4L;

    private final long dataCenterIdBits = 2L;


    private final long workerIdShift = sequenceBits;

    private final long dataCenterIdShift = sequenceBits + workerIdBits;

    private final long timestampLeftShift = sequenceBits + workerIdBits + dataCenterIdBits;


    private long workerId;

    private long dataCenterId;

    private String domainUniId;

    private String COLON = ":";

    public final static String DATACENTERID = "dataCenterId";

    public final static String WORKERID = "workerId";


    public static void main(String[] args) {
        IdManager idManager = new IdManager();
        System.out.println(idManager.nextId());
        System.out.println(idManager.nextId());
        System.out.println(idManager.nextId());
        System.out.println(idManager.nextId());

    }

    protected long timeGen() {
        return System.currentTimeMillis();
    }
    public synchronized long nextId() {

        long timestamp = timeGen();
        if (timestamp < lastTimestamp) {
            throw new RuntimeException(
                    String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
        }
        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }
        lastTimestamp = timestamp;
        long id = ((timestamp - startEpoch) << timestampLeftShift)
                | (dataCenterId << dataCenterIdShift)
                | (workerId << workerIdShift)
                | sequence;

        return id;
    }

    protected long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }
}
